/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "物理体.h"

#include "../插座/list/list物理物体插座.h"
#include "../插座/list/list矢量插座.h"
#include "../插座/list/list物体插座.h"
#include "../插座/list/list数值插座.h"
#include "../插座/通用插座.h"
#include "../插座/C_数值插座.h"
#include "Context/当前默认操作数据.h"
#include "异步解算/物理异步解算.h"

#include <面/面.h>
#include <物理/物理.h>
#include <Range.h>

#include <NvFleX封装.h>



S_单色点材质* g_点材质 = nullptr;





static uint32 f_物理体类型转枚举索引(E_物理体类型 type) {
	uint8 物理体类型 = 0;
	switch (type)
	{
	case E_物理体类型::E_物理体_流体: 物理体类型 = 1; break;
	case E_物理体类型::E_物理体_柔体: 物理体类型 = 2; break;
	case E_物理体类型::E_物理体_布料: 物理体类型 = 3; break;
	case E_物理体类型::E_物理体_流入: 物理体类型 = 4; break;
	case E_物理体类型::E_物理体_刚体: 物理体类型 = 5; break;
	case E_物理体类型::E_物理体_控制: 物理体类型 = 6; break;
	case E_物理体类型::E_物理体_静态: 物理体类型 = 7; break;
	case E_物理体类型::E_物理体_车辆: 物理体类型 = 8; break;
	case E_物理体类型::E_物理体_流出: 物理体类型 = 9; break;
	default:
		break;
	}
	return 物理体类型;
}

static E_物理体类型 f_枚举索引转物理体类型(uint32 index) {
	switch (index)
	{
	case 1: return E_物理体类型::E_物理体_流体;
	case 2: return E_物理体类型::E_物理体_柔体;
	case 3: return E_物理体类型::E_物理体_布料;
	case 4: return E_物理体类型::E_物理体_流入;
	case 5: return E_物理体类型::E_物理体_刚体;
	case 6: return E_物理体类型::E_物理体_控制;
	case 7: return E_物理体类型::E_物理体_静态;
	case 8: return E_物理体类型::E_物理体_车辆;
	case 9: return E_物理体类型::E_物理体_流出;
	default:
		break;
	}
	return E_物理体类型::E_物理体_空;
}


static E_物理引擎 f_枚举索引转物理引擎类型(uint32 index) {
	switch (index)
	{
	case 1: return E_物理引擎::E_物理引擎_FleX;
	case 2: return E_物理引擎::E_物理引擎_PhysX;
	case 3: return E_物理引擎::E_物理引擎_FLIP;
	case 4: return E_物理引擎::E_物理引擎_PBF;
	case 5: return E_物理引擎::E_物理引擎_Bullet;
	case 6: return E_物理引擎::E_物理引擎_ODE;
	case 7: return E_物理引擎::E_物理引擎_NewTon;
	case 8: return E_物理引擎::E_物理引擎_Chrono;
	default:
		break;
	}
	return E_物理引擎::E_物理引擎_None;
}

/*static uint32 f_物理引擎类型枚转举索引(E_物理引擎 e) {
	switch (e)
	{
	case E_物理引擎::E_物理引擎_FleX: return 1;
	case E_物理引擎::E_物理引擎_PhysX: return 2;
	case E_物理引擎::E_物理引擎_FLIP: return 3;
	case E_物理引擎::E_物理引擎_PBF: return 4;
	case E_物理引擎::E_物理引擎_Bullet: return 5;
	case E_物理引擎::E_物理引擎_ODE: return 6;
	case E_物理引擎::E_物理引擎_NewTon: return 7;
	case E_物理引擎::E_物理引擎_Chrono: return 8;
	default:
		break;
	}
	return 0;
}*/










C_物理碰撞节点::C_物理碰撞节点(S_设备环境& ctx) : C_节点基类("物理碰撞节点") {
	m_Name = L"物理碰撞节点";
	
}

bool C_物理碰撞节点::f_update() {
	return false;
}


C_节点基类* f_node_加载物理碰撞节点(S_设备环境& ctx, FILE* f) {
	C_物理碰撞节点* node = new C_物理碰撞节点(ctx);
	return node;
}






C_物理几何体节点::C_物理几何体节点(S_设备环境& ctx) : C_节点基类(DEF_物理几何体节点) {
	m_Name = L"物理几何体";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物体_Array1D插座_I(L"物体");
	DEF_创建物理几何体_1D插座_O(L"物理体");

	m_物理引擎类型 = f_创建物理引擎类型属性数据();
	m_物理引擎类型.m_私有 = true;
	f_prop_enum(m_物理引擎类型) = E_物理引擎::E_物理引擎_Bullet;
	

	m_几何体类型 = f_alloc_EnumProp(nullptr,
		{ 
			{L"立方体", ""},
			{L"圆柱体", ""},
			{L"球体", ""},
			{L"胶囊", ""},
			{L"凸壳", ""},
			{L"平面", ""},
			

			{L"网格", ""},
		}
	, L"物理几何体类型", 0);

	m_几何体类型.m_私有 = true;
	f_prop_enum(m_几何体类型) = 0;

}

C_物理几何体节点::~C_物理几何体节点() {

}

bool C_物理几何体节点::f_update() {
	auto& 物体 = *DEF_物体插座_Array1D数据(f_get输入插座(1), 0);
	auto& 物理几何体 = *DEF_物理几何插座_1D数据(f_get输出插座(1), 0);

	uint32 num = 物体.size();
	uint32 old_num = 物理几何体.size();

	for (uint32 i = num; i < old_num; ++i) {
		delete 物理几何体[i];
	}
	物理几何体.resize(num);
	for (uint32 i = old_num; i < num; ++i) {
		物理几何体[i] = (new S_物理几何体);
	}

	if (f_prop_enum(m_几何体类型) != E_物理碰撞几何类型::E_碰撞几何_网格) {
		if (!num) {
			物理几何体.push_back(new S_物理几何体);
			num = 1;
		}
	}
	//std::string 物理体类型;
	//std::string 大小;

	switch (f_prop_enum(m_几何体类型)) {
	case E_物理碰撞几何类型::E_碰撞几何_方体:
		for (uint32 i = 0; i < num; ++i) {
			物理几何体[i]->m_Type = E_物理碰撞几何类型::E_碰撞几何_方体;
			物理几何体[i]->m_变换 = 物体[i]->m_变换;
			物理几何体[i]->m_绑定物体 = 物体[i];
		}
		break;
	default:
		break;
	}

	for (uint32 i = 0; i < num; ++i) {
		f_Phy_创建物理几何体(E_物理引擎(f_prop_enum(m_物理引擎类型)), 物理几何体[i]);
	}

	switch (f_prop_enum(m_物理引擎类型)) {
	case E_物理引擎::E_物理引擎_Bullet: {

		break;
	}
	default:
		break;
	}
	return false;
}

void C_物理几何体节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_物理几何体节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_加载物理几何体节点(S_设备环境& ctx, FILE* f) {
	C_物理几何体节点* node = new C_物理几何体节点(ctx);
	return node;
}

void f_node_保存物理几何体节点(C_节点基类* n, FILE* f) {
	C_物理几何体节点* node = dynamic_cast<C_物理几何体节点*>(n);
}





C_物理体节点::C_物理体节点(S_设备环境& ctx) : C_节点基类(DEF_物理体节点) {
	m_Name = L"物理体节点";						
	//m_物理体类型 = type;						// E_物理体类型::E_物理体_流体;
	m_插座改变后是否更新节点 = true;
	m_是否完成计算 = 0;


	m_物理体类型 = f_alloc_EnumProp(nullptr,
		{ {L"空", ""}

		, {L"流体", ""}
		, {L"柔体", ""}
		, {L"布料", ""}
		, {L"流入", ""}
		
		, {L"刚体", ""}
		, {L"控制", ""}
		, {L"静态", ""}
		, {L"车辆", ""}

		
		, {L"流出", ""}
		
		}
	, L"物理体类型", 0);

	
	
	f_prop_enum(m_物理体类型) = 5;
	m_物理体类型.m_私有 = true;

	m_物理引擎类型 = f_创建物理引擎类型属性数据();
	f_prop_enum(m_物理引擎类型) = E_物理引擎::E_物理引擎_Bullet;
	m_物理引擎类型.m_私有 = true;

	m_粒子最大数 = f_alloc_UI32Prop(nullptr, L"发射粒子最大数");
	f_prop_UI32(m_粒子最大数) = 1000;
	m_粒子最大数.m_私有 = true;

	m_填充方式 = f_alloc_EnumProp(nullptr,
		{ {L"实体", ""}
		, {L"表面", ""}
		}
	, L"填充方式", 0);
	m_填充方式.m_私有 = true;

	m_是否多线程 = f_alloc_BoolProp(nullptr, L"多线程");
	m_是否多线程.m_私有 = true;
	f_prop_Bool(m_是否多线程) = false;


	C_插座基类* socket;
	DEF_创建F32插座_v1_I(L"解析度");
	DEF_创建物体_Array1D插座_I(L"几何体");
	DEF_创建物理几何体_1D插座_I(L"物理体");
	
	DEF_创建物理体_1D插座_O(L"物理体");
	
	DEF_F32插座数据(f_get输入插座(1)) = 0.1;
	f_get输入插座(3)->f_set多输入();


	m_数据可视物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);
	f_ob_set数据槽数量(m_数据可视物体, 1);

	auto* mesh = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_VULKAN);
	m_数据可视物体->f_setData(mesh, 0);

	//f_NodeCtx_get当前独立显示物体();
	if (!g_点材质) {
		g_点材质 = new S_单色点材质(ctx);
	}
	f_ob_set材质(m_数据可视物体, g_点材质, 0);



	f_get输入插座(2)->f_set多输入();
}

C_物理体节点::~C_物理体节点() {
	auto& out物理体 = *DEF_物理体插座_1D数据(f_get输出插座(1), 0);
	for (auto& ob : out物理体) {

	}

	f_release_EnumProp(m_物理体类型);
	f_prop_Release(m_粒子最大数);
	f_prop_Release(m_填充方式);
	f_prop_Release(m_是否多线程);
}

bool C_物理体节点::f_update() {
	uint32 LinkNum = f_get输入插座(2)->f_getLinkNum();

	auto& out物理体 = *DEF_物理体插座_1D数据(f_get输出插座(1), 0);
	E_物理体类型 物理体类型 = f_枚举索引转物理体类型(f_prop_enum(m_物理体类型));
	E_物理引擎 物理引擎类型 = E_物理引擎(f_prop_enum(m_物理引擎类型));


	std::vector<S_物理体*> 新物理体;
	
	uint32 offset = 0;

	if (物理引擎类型 == E_物理引擎::E_物理引擎_Mujoco) {
		LinkNum = f_get输入插座(3)->f_getLinkNum();
		for (uint32 线ID = 0; 线ID < LinkNum; ++线ID) {
			auto& 物理几何体 = *DEF_物理几何插座_1D数据(f_get输入插座(3), 线ID);

			for (auto& ob : 物理几何体) {
				S_物理体* body = nullptr;
				if (offset >= out物理体.size()) {
					body = new S_物理体();
					out物理体.push_back(body);
				}
				else {
					body = out物理体[offset];
				}
				body->m_变换 = ob->m_变换;
				body->m_绑定物体 = ob->m_绑定物体;
				
				std::string 位置 = "pos = \" ";
				std::string 大小 = "size = \" ";
				std::string gepm_type;
				switch (ob->m_Type) {
				case E_物理碰撞几何类型::E_碰撞几何_方体:
					gepm_type = "box";
					break;
				case E_物理碰撞几何类型::E_碰撞几何_圆柱:
					break;
				case E_物理碰撞几何类型::E_碰撞几何_球体:
					break;
				case E_物理碰撞几何类型::E_碰撞几何_胶囊:
					break;
				case E_物理碰撞几何类型::E_碰撞几何_凸壳:
					break;
				case E_物理碰撞几何类型::E_碰撞几何_平面:
					gepm_type = "plane";
					break;
				case E_物理碰撞几何类型::E_碰撞几何_网格:
					break;
				}

				auto mat = f_ob_get实例变换矩阵((S_物体*)ob->m_绑定物体, 0);
				//auto 旋转矩阵 = f_mat4_构建缩放矩阵({ 1, -1, 1 }) * mat * f_mat44_构建行式旋转矩阵(90, { 1,0,0 });
				
				//f_mat44_to_33(mat);
				//vec4 q = mat3x3_to_quat(f_mat44_to_33(旋转矩阵));
				
				vec3 pos = mat * vec3{ 0,0,0 };
				//vec3 rot = f_mat44_构建行式旋转矩阵(-90, { 1,0,0 }) * body->m_变换.rotation;
				vec3 rot = body->m_变换.rotation;

				位置 += f_浮点数值转字符串(body->m_变换.location.x) + " ";
				位置 += f_浮点数值转字符串(body->m_变换.location.z) + " ";
				位置 += f_浮点数值转字符串(body->m_变换.location.y) + " ";
				位置 += "\" ";

				大小 += f_浮点数值转字符串(body->m_变换.scale.x) + " ";
				大小 += f_浮点数值转字符串(body->m_变换.scale.z) + " ";
				大小 += f_浮点数值转字符串(body->m_变换.scale.y) + " ";
				大小 += "\" ";

				std::string 旋转 = " euler = \" ";
				//std::string 旋转 = " quat = \" ";
				rot.x = -body->m_变换.rotation.x;
				rot.y = -body->m_变换.rotation.y;
				rot.z = -body->m_变换.rotation.z;
				vec4 q = f_graph_欧拉角转四元数(rot);
				//旋转 += f_浮点数值转字符串(q.w) + " ";
				//auto rotMat = f_mat3x3_从全局旋转角构建矩阵(rot);
				auto rotMat = f_mat44_构建XYZ旋转矩阵(body->m_变换);
				//rotMat = f_mat44_构建行式旋转矩阵(-90, { 1.0f,0.0f,0.0f }) * rotMat;
				//rotMat = f_mat4_构建缩放矩阵({1,-1,1}) * rotMat;
				
				//rot = f_graph_旋转矩阵转欧拉角(f_mat44_to_33(rotMat));
				q = f_graph_旋转角转四元数(rot);
				
				//q = f_graph_quat反向(mat3x3_to_quat(f_mat44_to_33(f_mat44_构建行式旋转矩阵(-90, { 1,0,0 }) * rotMat)));
				//旋转 += f_浮点数值转字符串((q.w)) + " ";
				//旋转 += f_浮点数值转字符串((q.x)) + " ";
				//旋转 += f_浮点数值转字符串((q.y)) + " ";
				//旋转 += f_浮点数值转字符串((q.z)) + " ";
				//if (rot.z >= 180) rot.x = -rot.x;
				旋转 += f_浮点数值转字符串((rot.z)) + " ";
				旋转 += f_浮点数值转字符串((rot.x)) + " ";
				旋转 += f_浮点数值转字符串((rot.y)) + " ";
				
				旋转 += "\" ";

				body->m_XML = "	<body " + 位置 + 旋转 +"> \n";

				switch (物理体类型)
				{
				case E_物理体类型::E_物理体_刚体:
					body->m_XML += "	<freejoint /> \n";
					break;
				case E_物理体类型::E_物理体_静态:
					break;
				default:
					break;
				}
				
				body->m_XML += "	<geom type = \"" + gepm_type + "\" " + 大小 +"/> \n";
				body->m_XML += "	</body> \n";
				++offset;
			}
		}

	}
	else if (物理引擎类型 == E_物理引擎::E_物理引擎_Bullet) {
		LinkNum = f_get输入插座(3)->f_getLinkNum();

		for (uint32 线ID = 0; 线ID < LinkNum; ++线ID) {
			auto& 物理几何体 = *DEF_物理几何插座_1D数据(f_get输入插座(3), 线ID);
			S_物理体* body = nullptr;

			for (auto& ob : 物理几何体) {
				S_物理体* body = nullptr;
				if (offset >= out物理体.size()) {
					To_重新创建:
					body = f_Phy_create物理体(*ob, nullptr, 物理引擎类型);
					out物理体.push_back(body);
				}
				else {
					body = out物理体[offset];
					if (body->m_物理引擎枚举 != 物理引擎类型) {
						f_Phy_销毁物理体(body);
						goto To_重新创建;
					}
				}
				++offset;
				body->m_变换 = ob->m_变换;

				switch (物理体类型)
				{
				case E_物理体类型::E_物理体_刚体:
					
					break;
				case E_物理体类型::E_物理体_静态:
					break;
				default:
					break;
				}

			}
		}
	}
	else {
		for (uint32 线ID = 0; 线ID < LinkNum; ++线ID) {
			auto& 物体 = *DEF_物体插座_Array1D数据(f_get输入插座(2), 线ID);
			S_物理体* body = nullptr;

			if (物理引擎类型 == E_物理引擎::E_物理引擎_FleX) {
				for (auto& ob : 物体) {
					if (offset >= out物理体.size()) {
						body = new S_物理体();
						out物理体.push_back(body);
					}
					else {
						body = out物理体[offset];
					}
					f_Phy_切换物理体类型(物理引擎类型, body, 物理体类型);
					body->m_绑定物体 = ob;
					++offset;
				}
			}
			//out物理体.insert(out物理体.begin(), 物理体.begin(), 物理体.end());
		}
	}

	


	//删除多余的物理体
	if (offset < out物理体.size()) {
		int32 删除数量 = out物理体.size() - offset;
		while (删除数量 > 0) {
			f_Phy_销毁物理体(out物理体.back());
			out物理体.pop_back();
			--删除数量;
		}
	}


	if (m_是否完成计算 == 0) {
		if (f_prop_Bool(m_是否多线程)) {
			m_是否完成计算 = 1;
			bool 是否更新 = f_NodeCtx_物理模拟线程入栈(this);
			return true;
		}
		else {
			f_异步解算();
		}
	}
	else if (m_是否完成计算 == 2) {
		m_是否完成计算 = 0;
		f_get输出插座(1)->m_有新数据 = true;
	}

	return false;
}

void C_物理体节点::f_异步解算() {
	E_物理体类型 物理体类型 = f_枚举索引转物理体类型(f_prop_enum(m_物理体类型));
	E_物理引擎 物理引擎类型 = f_枚举索引转物理引擎类型(f_prop_enum(m_物理引擎类型));

	auto& out物理体 = *DEF_物理体插座_1D数据(f_get输出插座(1), 0);
	float32 解析度 = DEF_F32插座数据(f_get输入插座(1));

	if (物理引擎类型 == E_物理引擎::E_物理引擎_FleX) {

		uint32 num = out物理体.size();
#pragma omp parallel for
		for (int32 i = 0; i < num; ++i) {
			//for (auto& ob : 物理体) {
			auto& ob = out物理体[i];

			S_物体* obj = dynamic_cast<S_物体*>(ob->m_绑定物体);
			S_体素* vo = f_Phy_get发射源体素(ob);
			if (!vo) {
				std::cout << "物理体类型还未支持" << std::endl;
				continue;
			}

			if (f_prop_enum(m_填充方式)) {
				S_Mesh* e = f_ob_fromMesh(obj);
				//for (auto& e : meshs) {
				std::vector<S_VN> vn;
				std::vector<uvec3> index;
				f_surface_get顶点数据(e, vn);
				f_surface_get顶点索引(e, index);

				std::vector<S_VN> 采样坐标法线;
				f_graph_从面采样坐标(采样坐标法线, vn, index, 解析度 * 2);

				vo->m_坐标.reserve(采样坐标法线.size());
				vo->m_法线.reserve(采样坐标法线.size());
				for (auto& e : 采样坐标法线) {
					vo->m_坐标.push_back(e.vert);
					vo->m_法线.push_back({ e.normal.x, e.normal.y, e.normal.z, 1.0f });
				}

			}
			else {
				f_fromMesh创建体素(*vo, f_ob_fromMesh(obj), obj->f_get位置(), obj->f_get旋转(), obj->f_get缩放(), 解析度 * 2);
			}

			if (!(vo->m_坐标.size())) continue;
			switch (物理体类型) {
			case E_物理体类型::E_物理体_流体: {

				break;
			}

			case E_物理体类型::E_物理体_流入: {
				f_Phy_set粒子发射最大数量(ob, f_prop_UI32(m_粒子最大数));

				break;
			}

			case E_物理体类型::E_物理体_刚体: {

				break;
			}
			}

			ob->f_setPos(obj->f_get位置());
			ob->f_setRot(obj->f_get旋转());
			ob->f_setScl(obj->f_get缩放());
		}

	}

	m_是否完成计算 = 2;
}

void C_物理体节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	
	f_prop_Load(m_物理引擎类型, f);
	f_prop_Load(m_物理体类型, f);
	f_prop_Load(m_粒子最大数, f);
	f_prop_Load(m_填充方式, f);
	f_prop_Load(m_是否多线程, f);
}

void C_物理体节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	f_prop_Save(m_物理引擎类型, f);
	f_prop_Save(m_物理体类型, f);
	f_prop_Save(m_粒子最大数, f);
	f_prop_Save(m_填充方式, f);
	f_prop_Save(m_是否多线程, f);
}

S_物体* C_物理体节点::f_get虚拟体() {
	if (f_get输入插座(2)->f_isLink() == false) {
		return m_数据可视物体;
	}
	return nullptr;
}

C_节点基类* f_node_加载物理体节点(S_设备环境& ctx, FILE* f) {
	//fread(&(((S_PropValueEnum*)node->m_计算方式.m_Value)->m_当前选项), sizeof(uint8), 1, f);
	C_物理体节点* node = new C_物理体节点(ctx);
	return node;
}

void f_node_保存物理体节点(C_节点基类* n, FILE* f) {
	C_物理体节点* node = dynamic_cast<C_物理体节点*>(n);

	//uint32 物理体类型 = (((S_PropValueEnum*)node->m_物理体类型.m_Value)->m_当前选项);
	//fwrite(&物理体类型, sizeof(uint32), 1, f);
}










C_物理体添加节点::C_物理体添加节点(S_设备环境& ctx) : C_节点基类("物理体添加节点") {
	m_Name = L"物理体节点";

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(L"物理引擎");
	DEF_创建物理体_1D插座_I(L"物理体");
	//DEF_创建对象1D插座_I("对象");
	//DEF_创建物理几何插座_I("几何");
	DEF_创建物理引擎插座_O(L"物理引擎");
	//DEF_创建物理体Array1D插座_O("物理体");
}

bool C_物理体添加节点::f_update() {
	auto* 解算器 = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	
	//auto& 输出解算器 = *DEF_物理解算器插座值(f_get输出插座(1), 0);
	f_get输出插座(1)->f_setData(解算器);

	if (解算器) {
		uint16 num = f_get输入插座Num();
		for (uint32 i = 2; i < num; ++i) {
			auto& 物理体 = *DEF_物理体插座_1D数据(f_get输入插座(i), 0);
			f_Phy_添加物理体(解算器, 物理体);
		}
		
	}

	//auto* out物理体 = DEF_物理体_1D插座数据(f_get输出插座(2), 0);
	return false;
}

C_插座基类* C_物理体添加节点::f_动态添加插座(E_插座方向 方向) {
	C_插座基类* socket = nullptr;
	return socket;

	E_数据赋值方式 插座操作方式;

	uint16 num = f_get输入插座Num();
	if (num >= 3 && f_get输入插座(num - 2)->f_isLink() == false) {
		//return { nullptr, E_数据赋值方式::e_赋值_None };
	}

	switch (方向)
	{
	case e_插座Type_输入: {
		DEF_创建物理体_1D插座_I(L"源1");

		插座操作方式 = E_数据赋值方式::e_赋值_添加;
		break;
	}
	case e_插座Type_输出: {

		插座操作方式 = E_数据赋值方式::e_赋值_添加;
		break;
	}
	//default:
	//	return { nullptr, E_数据赋值方式::e_赋值_None };
	}

	f_set是否要更新(true);
	return socket;
}

C_节点基类* f_node_加载物理体添加节点(S_设备环境& ctx, FILE* f) {
	C_物理体添加节点* node = new C_物理体添加节点(ctx);
	return node;
}

void f_node_保存物理体添加节点(C_节点基类* n, FILE* f) {
	C_物理体添加节点* node = dynamic_cast<C_物理体添加节点*>(n);

}




C_取物理体节点::C_取物理体节点(S_设备环境& ctx) : C_节点基类(DEF_取物理体节点) {
	m_Name = L"取物理体";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(L"物理引擎");
	DEF_创建物理体_1D插座_O(L"物理体");

	m_物理几何类型 = f_创建物理几何类型属性数据();
	m_物理几何类型.m_私有 = true;
	f_prop_enum(m_物理几何类型) = E_物理碰撞几何类型::E_碰撞几何_方体;
}

C_取物理体节点::~C_取物理体节点() {
}

bool C_取物理体节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	auto& bodys = *DEF_物理体插座_1D数据(f_get输出插座(1), 0);

	if (m_Physics) {
		bodys = f_phy_get物理体(m_Physics, E_物理碰撞几何类型(f_prop_enum(m_物理几何类型)));
	}
	else {
		bodys.clear();
	}
	
	return false;
}

void C_取物理体节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_物理几何类型, f);
}

void C_取物理体节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_物理几何类型, f);
}

C_节点基类* f_node_加载取物理体节点(S_设备环境& ctx, FILE* f) {
	C_取物理体节点* node = new C_取物理体节点(ctx);
	return node;
}

void f_node_保存取物理体节点(C_节点基类* n, FILE* f) {
	C_取物理体节点* node = dynamic_cast<C_取物理体节点*>(n);
}





C_物理体绑定物体节点::C_物理体绑定物体节点(S_设备环境& ctx) : C_节点基类(DEF_物理体绑定物体节点) {
	m_Name = L"绑定物体";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(L"物理引擎");
	DEF_创建物理体_1D插座_I(L"物理体");
	DEF_创建物体_Array1D插座_I(L"绑定物体");
	
	DEF_创建物理引擎插座_O(L"物理引擎");
	f_get输入插座(1)->f_set单输入();
	//m_物理几何类型 = f_创建物理几何类型属性数据();
	//m_物理几何类型.m_私有 = true;
	//f_prop_enum(m_物理几何类型).m_当前选项 = E_物理碰撞几何类型::E_碰撞几何_方体;

}

C_物理体绑定物体节点::~C_物理体绑定物体节点() {
}

bool C_物理体绑定物体节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	auto& bodys = *DEF_物理体插座_1D数据(f_get输入插座(2), 0);
	auto& obs = *DEF_物体插座_Array1D数据(f_get输入插座(3), 0);

	auto body_ptr = bodys.data();
	auto ob_ptr = obs.data();

	uint32 num = bodys.size();
	if (num <= obs.size()) {
		for (uint32 i = 0; i < num; ++i) {
			body_ptr[i]->m_绑定物体= ob_ptr[i];
			ob_ptr[i]->m_ID = body_ptr[i]->m_ID;
		}
		if (m_Physics) f_Phy_内部网格填充绑定物体(m_Physics, bodys);
	}
	f_get输出插座(1)->f_setData(m_Physics);

	return false;
}

void C_物理体绑定物体节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_物理体绑定物体节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_加载物理体绑定物体节点(S_设备环境& ctx, FILE* f) {
	C_物理体绑定物体节点* node = new C_物理体绑定物体节点(ctx);
	return node;
}

void f_node_保存物理体绑定物体节点(C_节点基类* n, FILE* f) {
	C_物理体绑定物体节点* node = dynamic_cast<C_物理体绑定物体节点*>(n);
}





C_物理引擎内部几何节点::C_物理引擎内部几何节点(S_设备环境& ctx) : C_节点基类(DEF_物理引擎内部几何节点) {
	m_Name = L"内部几何";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(L"物理引擎");
	DEF_创建物理引擎插座_O(L"物理引擎");

}

C_物理引擎内部几何节点::~C_物理引擎内部几何节点() {
}

bool C_物理引擎内部几何节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1));
	if (m_Physics) {
		//f_Phy_内部网格填充绑定物体(m_Physics);
	}
	
	f_get输出插座(1)->f_setData(m_Physics);
	return false;
}

void C_物理引擎内部几何节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_物理引擎内部几何节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_加载物理引擎内部几何节点(S_设备环境& ctx, FILE* f) {
	C_物理引擎内部几何节点* node = new C_物理引擎内部几何节点(ctx);
	return node;
}

void f_node_保存物理引擎内部几何节点(C_节点基类* n, FILE* f) {
	C_物理引擎内部几何节点* node = dynamic_cast<C_物理引擎内部几何节点*>(n);
}





C_发射节点::C_发射节点(S_设备环境& ctx) : C_节点基类("发射节点") {
	m_Name = L"物理体节点";

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(L"物理解算器");
	DEF_创建物理体_1D插座_I(L"发射源");
	//DEF_创建UI32插座_I(L"发射量");
	DEF_创建F32插座_v1_I(L"速率");
	DEF_创建F32_Array1D插座_I(L"速度");
	//DEF_创建F32插座_I("采样大小");
	//DEF_创建对象1D插座_I("对象");
	//DEF_创建物理几何插座_I("几何");
	DEF_创建物理引擎插座_O(L"物理解算器");
	
	float32 速率 = 1.0;
	f_get输入插座(3)->f_setData(&速率);

	(*DEF_F32_Array1D插座数据(f_get输入插座(4)))[0] = 1.0;
}

bool C_发射节点::f_update() {
	auto* 解算器 = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	
	if (!解算器) return false;
	f_get输出插座(1)->f_setData(解算器);

	auto& 物理体 = *DEF_物理体插座_1D数据(f_get输入插座(2), 0);
	//uint32 最大粒子数 = *DEF_F32插座数据(f_get输入插座(3));
	float32 速率 = DEF_F32插座数据(f_get输入插座(3));
	auto& 速度 = *DEF_F32_Array1D插座数据(f_get输入插座(4));


	switch (解算器->m_IdType)
	{
	case E_物理引擎::E_物理引擎_FleX: {
		for (auto& e : 物理体) {
			S_体素* vo = f_Phy_get发射源体素(e);
			if (!vo) continue;

			//uvec2 区间 = f_Phy_get粒子区间(e);
			uvec4 区间 = f_Phy_get粒子发射区间(e, 速率);
			//e->m_全局偏移;
			C_Mat44 mat = f_从变换构建矩阵(e->f_getLoc(), e->f_getRot(), e->f_getScl());
			
			auto newPoint = vec_矩阵变换(vo->m_坐标, mat);
			auto speed = vec_Mul(vo->m_法线, 速度[0]);

			bool 添加 = true;
			if (区间.z == 0xffffffff) {
				添加 = false;
			}
			f_NvFleX_发射(解算器->f_getID(), { 区间.x, 区间.y }, newPoint.data(), speed.data(), 添加);
		}

		break;
	}

	default:
		break;
	}

	return false;

	std::vector<S_Mesh*> meshs;

	auto& s2 = *DEF_引用插座数据(f_get输入插座(2), 0);
	switch (s2.m_Type)
	{
	case E_值类型::e_Type_Object: {
		auto* ob = DEF_引用转物体(s2);
		auto* mesh = f_ob_fromTranformMesh(ob);
		meshs.push_back(mesh);
		break;
	}
	case E_值类型::e_Type_Mesh: {

		break;
	}
	default:
		break;
	}


	uint32 num = meshs.size();
	if (num && 解算器) {
		uint32 发射量 = DEF_UI32插座数据(f_get输入插座(3));


		std::vector<S_物理体*> bodys;
		bodys.reserve(meshs.size());

		float32 间隔 = f_Phy_get粒子大小(解算器);
		for (uint32 i = 0; i < num; ++i) {
			S_Mesh* e = meshs[i];
		//for (auto& e : meshs) {
			std::vector<S_VN> vn;
			std::vector<uvec3> index;
			f_surface_get顶点数据(e, vn);
			f_surface_get顶点索引(e, index);


			std::vector<S_VN> 采样坐标法线;
			f_graph_从面采样坐标(采样坐标法线, vn, index, 间隔 * 2);
			for (auto& e : 采样坐标法线) {
				vec_mul(&(e.normal), 25.5);
				//vec_add(&(e.normal), e.vert);
			}


			S_物理体* body = nullptr;
			if (i >= 物理体.size()) {
				body = f_Phy_create粒子发射(解算器, 发射量);
				物理体.push_back(body);
			}
			else {
				body = 物理体[i];
			}
			
			f_Phy_set粒子发射最大数量(body, 发射量);
			f_Phy_set粒子发射(body, 采样坐标法线);
			bodys.push_back(body);

		}
		f_Phy_添加物理体(解算器, bodys);

		
	}


	for (auto& e : meshs) delete e;

	return false;
}

C_节点基类* f_node_加载发射节点(S_设备环境& ctx, FILE* f) {
	C_发射节点* node = new C_发射节点(ctx);
	return node;
} 

void f_node_保存发射节点(C_节点基类* n, FILE* f) {
	C_发射节点* node = dynamic_cast<C_发射节点*>(n);

}










C_物理变换回写节点::C_物理变换回写节点(S_设备环境& ctx) : C_节点基类("物理变换回写节点") {
	m_Name = L"物理变换回写节点";
	C_插座基类* socket;

	DEF_创建物理体_1D插座_I(L"物理体");

	auto& phyBody = *DEF_物理体插座_1D数据(f_get输入插座(1), 0);

	uint32 num = uint32(phyBody.size());
	auto* data = phyBody.data();
	for(uint32 i=0; i<num; ++i){
		switch (data[i]->m_Type) {
			case E_物理体类型::E_物理体_刚体:
				break;

			case E_物理体类型::E_物理体_车辆:
				break;

			case E_物理体类型::E_物理体_流体:
				data[i];
				break;
			default:
				break;
		} 
	}
}

bool C_物理变换回写节点::f_update() {
	return false;
}



C_节点基类* f_node_加载物理变换回写节点(S_设备环境& ctx, FILE* f) {
	C_物理变换回写节点* node = new C_物理变换回写节点(ctx);
	return node;
}


